


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>  项目二-面试题-Vue项目中那些数组处理vue无法劫持，及原理分析 |    经验分享</title>
  <!-- 标签页图标 -->
  

  <!-- 图标库 -->
  <link href="https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css" rel="stylesheet">
  <!-- 动画库 -->
  
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fushaolei/cdn-white@1.0/css/animate.css"/>
  
  <!-- css文件 -->
  
<link rel="stylesheet" href="/blog/css/white.css">

  
<link rel="stylesheet" href="/blog/css/highlight.css">

  <!-- 代码高亮 -->
  
<meta name="generator" content="Hexo 5.0.0"></head>


<body>

<div class="menu-outer">
    <div class="menu-inner">
      <div class="menu-site-name  animate__animated  animate__fadeInUp">
        <a href="/blog/">
          经验分享
        </a>
        
      </div>
      <div class="menu-group">
        <ul class="menu-ul">
        
          <a href="/blog/" class="nav-link">
            <li class="menu-li  animate__animated  animate__fadeInUp">
              首页
            </li>
          </a>
        
          <a href="/blog/archives" class="nav-link">
            <li class="menu-li  animate__animated  animate__fadeInUp">
              文章列表
            </li>
          </a>
        
        
        
        <a href="/blog/search">
          <li class="menu-li  animate__animated  animate__fadeInUp">
            <i class="ri-search-line"></i>
          </li>
        </a>
        
          <li class="menu-li animate__animated  animate__fadeInUp" id="mobile-menu">
            <i class="ri-menu-line"></i>
          </li>
        
        </ul>

      </div>

    </div>
</div>
<div id="mobile-main" class="animate__animated  animate__fadeIn">
  <div class="mobile-menu-inner">
    <div class="mobile-menu-site-name animate__animated  animate__fadeInUp">
      <a href="/blog/">
        经验分享
      </a>
    </div>
    <div class="mobile-menu-group" id="mobile-close">
      <i class="ri-close-line"></i>
    </div>

  </div>

  <div class="mobile-menu-div">
  
    <a href="/blog/" class="mobile-nav-link">
      <div class="mobile-menu-child animate__animated  animate__fadeInUp">
        <span>首页</span>
      </div>
    </a>
  
    <a href="/blog/archives" class="mobile-nav-link">
      <div class="mobile-menu-child animate__animated  animate__fadeInUp">
        <span>文章列表</span>
      </div>
    </a>
  
  
    <a href="/blog/search">  
      <div class="mobile-menu-child  animate__animated  animate__fadeInUp">
        <i class="ri-search-line"></i>
      </div>
    </a>
    
  </div>


</div>

<div class="body-outer">
  <div class="body-inner">
    
<article class="post-inner">
  <div class="post-content-outer">
    <div class="post-intro">
      <div class="post-title animate__animated  animate__fadeInUp">项目二-面试题-vue项目中那些数组处理vue无法劫持，及原理分析</div>
      <div class="meta-intro animate__animated  animate__fadeInUp">Aug 18 2020</div>
      
    </div>
    <div class="post-content-inner">
      <div class="post-content-inner-space">

      </div>
      <div class="post-content-main animate__animated  animate__fadeInUp">
        <!-- top型目录 -->
        
        <h3 id="目的"><a href="#目的" class="headerlink" title="目的"></a>目的</h3><ol>
<li>给大家讲一道面试题。</li>
<li>帮助大家学会如何在项目中去思考总结。</li>
<li>从项目中进行提高：大家现在和未来都会做大量的项目，接下来我准备了一个项目中的面试题，来抛砖引玉下，希望大家多去思考下我们项目中为什么这么去写。</li>
</ol>
<h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><p><strong>请谈谈你在项目中哪些数据操作不会被vue劫持，我们怎么处理</strong></p>
<p>或</p>
<p><strong>vue官方说不能直接对数组进行修改怎么理解？那么你项目中有些地方涉及到了数组内容的修改？你是怎么做的？</strong></p>
<p><strong>这样做的原理是什么？</strong></p>
<h3 id="解析过程（遇到这类问题的思路）"><a href="#解析过程（遇到这类问题的思路）" class="headerlink" title="解析过程（遇到这类问题的思路）"></a>解析过程（遇到这类问题的思路）</h3><p>这类问题，主要考察3个方面，</p>
<ol>
<li>vue基础- 响应式的理解。</li>
<li>项目经验（我们有没有做项目深入思考的习惯）。</li>
<li>原理：（造飞机）array和set源码解释。（+2k）</li>
</ol>
<p><strong>大家回答的越深入给面试官的印象就会越好，谈薪资就能谈的越高。</strong></p>
<ol>
<li><p>我们先想下这个问题能还是不能。</p>
<p>不能</p>
<p>因为这句话是在 vue 响应式中提到的,下面式官网的截图</p>
</li>
</ol>
<p>
        <span class="lazyload-img-span">
        <img   
           data-src="./Snipaste_2020-08-18_09-15-31.png" >
        </sapn>
      </p>
<p>总结： 不能，因为vue 使用的方法 <code>Object.defineProperty</code> 有限制，<strong>Vue不能检测</strong>直接设置数组的变化，因此不能<strong>直接设置</strong>数组。</p>
<p>解决方案：</p>
<p>例如：Vue 不能检测以下数组的变动：</p>
<ol>
<li>当你利用索引直接设置一个数组项时，例如：<code>vm.items[indexOfItem] = newValue</code></li>
<li>当你修改数组的长度时，例如：<code>vm.items.length = newLength</code></li>
</ol>
<p>这里要突出一个<strong>直接</strong>。</p>
<ol start="2">
<li><p>对这个问题进行进详细的阐述，可以举例子。（先说说文档提供的解决方法）</p>
<p>如：</p>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span><br><span class="line">  data: &#123;</span><br><span class="line">    items: [<span class="string">&#x27;a&#x27;</span>, <span class="string">&#x27;b&#x27;</span>, <span class="string">&#x27;c&#x27;</span>]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line">vm.items[<span class="number">1</span>] = <span class="string">&#x27;x&#x27;</span> <span class="comment">// 不是响应性的</span></span><br><span class="line">vm.items.length = <span class="number">2</span> <span class="comment">// 不是响应性的</span></span><br></pre></td></tr></table></figure>

<p>​    这是两个数组的操作类。一个是修改数组内的值，一个是修改数组的长度。</p>
<p>​    解决方案</p>
<p>​    一个是修改数组内的值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Vue.set</span></span><br><span class="line">Vue.set(vm.items, indexOfItem, newValue)</span><br></pre></td></tr></table></figure>

<p>​    修改数组的长度</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Array.prototype.splice</span></span><br><span class="line">vm.items.splice(indexOfItem, <span class="number">1</span>, newValue)</span><br></pre></td></tr></table></figure>

<p>案例： test1全部代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;div v-for&#x3D;&quot;(val, index) in items&quot; :key&#x3D;&quot;index&quot;&gt;&#123;&#123; val &#125;&#125;&lt;&#x2F;div&gt;</span><br><span class="line">    &lt;button @click&#x3D;&quot;setItemsErr&quot;&gt;</span><br><span class="line">      改变-错误方法</span><br><span class="line">    &lt;&#x2F;button&gt;</span><br><span class="line">    &lt;button @click&#x3D;&quot;setItemsSuc&quot;&gt;</span><br><span class="line">      改变-正确方法</span><br><span class="line">    &lt;&#x2F;button&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      items: [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    &#x2F;&#x2F; 错误方法</span><br><span class="line">    setItemsErr() &#123;</span><br><span class="line">      &#x2F;&#x2F; 直接赋值</span><br><span class="line">      this.items[1] &#x3D; &quot;x&quot;;</span><br><span class="line">      &#x2F;&#x2F; 直接修改长度</span><br><span class="line">      this.items.length &#x3D; 2;</span><br><span class="line">    &#125;,</span><br><span class="line">    setItemsSuc() &#123;</span><br><span class="line">      &#x2F;&#x2F; 使用set 方法改变值</span><br><span class="line">      this.$set(this.items, 1, &quot;x&quot;);</span><br><span class="line">      &#x2F;&#x2F; 使用 数组原型中 splice 修改值</span><br><span class="line">      setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">        this.items.splice(1, 1);</span><br><span class="line">      &#125;, 2000);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>解析来补充回答：这是通过使用 $set 和 splice 来改变数组的。（+分）（总结我们描述的案例）</p>
<ol start="3">
<li>在项目中我们修改数组的地方。</li>
</ol>
<p>如下：</p>
<ol>
<li><p>增加评论列表或文章列表中    使用了 push 去添加数据，其中还用到了 … es6 解构构的方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;van-cell v-for&#x3D;&quot;(item, idx) in list&quot; :key&#x3D;&quot;idx&quot; :title&#x3D;&quot;item.title&quot;&gt;</span><br><span class="line">      &lt;div slot&#x3D;&quot;label&quot;&gt;</span><br><span class="line">        &lt;!-- 文字说明 --&gt;</span><br><span class="line">        &lt;div class&#x3D;&quot;meta&quot;&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.aut_name &#125;&#125;&lt;&#x2F;span&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.comm_count &#125;&#125;评论&lt;&#x2F;span&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.pubdate &#125;&#125;&lt;&#x2F;span&gt;</span><br><span class="line">        &lt;&#x2F;div&gt;</span><br><span class="line">      &lt;&#x2F;div&gt;</span><br><span class="line">    &lt;&#x2F;van-cell&gt;</span><br><span class="line">    &lt;van-button type&#x3D;&quot;primary&quot; @click&#x3D;&quot;add&quot;&gt;添加文章&lt;&#x2F;van-button&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      list: [</span><br><span class="line">        &#123;</span><br><span class="line">          title: &quot;天天向上&quot;,</span><br><span class="line">          aut_name: &quot;李林森&quot;,</span><br><span class="line">          comm_count: 1,</span><br><span class="line">          pubdate: 2002</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          title: &quot;好好学习&quot;,</span><br><span class="line">          aut_name: &quot;李林森&quot;,</span><br><span class="line">          comm_count: 1,</span><br><span class="line">          pubdate: 2002</span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    add() &#123;</span><br><span class="line">      const res &#x3D; [</span><br><span class="line">        &#123;</span><br><span class="line">          title: &quot;好好学习,天天向上&quot;,</span><br><span class="line">          aut_name: &quot;李林森&quot;,</span><br><span class="line">          comm_count: 1,</span><br><span class="line">          pubdate: Date.now()</span><br><span class="line">        &#125;</span><br><span class="line">      ];</span><br><span class="line">      &#x2F;&#x2F; es6解构和push增加数组的内容</span><br><span class="line">      this.list.push(...res);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>效果图</p>
<p>
        <span class="lazyload-img-span">
        <img   
           data-src="./Snipaste_2020-08-18_12-52-41.png" >
        </sapn>
      </p>
</li>
<li><p>本地删除文章操作 </p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;van-cell v-<span class="keyword">for</span>=<span class="string">&quot;(item, idx) in list&quot;</span> :key=<span class="string">&quot;idx&quot;</span> :title=<span class="string">&quot;item.title&quot;</span>&gt;</span><br><span class="line">      &lt;div slot=<span class="string">&quot;label&quot;</span>&gt;</span><br><span class="line">        &lt;!-- 文字说明 --&gt;</span><br><span class="line">        &lt;div <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;meta&quot;</span>&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.aut_name &#125;&#125;&lt;/span&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.comm_count &#125;&#125;评论&lt;/span&gt;</span><br><span class="line">          &lt;span&gt;&#123;&#123; item.pubdate &#125;&#125;&lt;/span&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    &lt;/van-cell&gt;</span><br><span class="line">    &lt;van-button type=<span class="string">&quot;primary&quot;</span> @click=<span class="string">&quot;add&quot;</span>&gt;添加文章&lt;/van-button&gt;</span><br><span class="line">    &lt;van-button type=<span class="string">&quot;primary&quot;</span> @click=<span class="string">&quot;deletes&quot;</span>&gt;删除文章&lt;/van-button&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      list: [</span><br><span class="line">        &#123;</span><br><span class="line">          title: <span class="string">&quot;天天向上&quot;</span>,</span><br><span class="line">          aut_name: <span class="string">&quot;李林森&quot;</span>,</span><br><span class="line">          comm_count: <span class="number">1</span>,</span><br><span class="line">          pubdate: <span class="number">2002</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          title: <span class="string">&quot;好好学习&quot;</span>,</span><br><span class="line">          aut_name: <span class="string">&quot;李林森&quot;</span>,</span><br><span class="line">          comm_count: <span class="number">1</span>,</span><br><span class="line">          pubdate: <span class="number">2002</span></span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    add() &#123;</span><br><span class="line">      <span class="keyword">const</span> res = [</span><br><span class="line">        &#123;</span><br><span class="line">          title: <span class="string">&quot;好好学习,天天向上&quot;</span>,</span><br><span class="line">          aut_name: <span class="string">&quot;李林森&quot;</span>,</span><br><span class="line">          comm_count: <span class="number">1</span>,</span><br><span class="line">          pubdate: <span class="built_in">Date</span>.now()</span><br><span class="line">        &#125;</span><br><span class="line">      ];</span><br><span class="line">      <span class="comment">// es6解构和push增加数组的内容</span></span><br><span class="line">      <span class="built_in">this</span>.list.push(...res);</span><br><span class="line">    &#125;,</span><br><span class="line">    deletes() &#123;</span><br><span class="line">      <span class="keyword">let</span> leg = <span class="built_in">this</span>.list.length;</span><br><span class="line">      <span class="built_in">this</span>.list.splice(leg - <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>使用了 splice 对数组中的指定位置进行删除。</p>
</li>
<li><p>本地对评论点赞操作</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;van-cell :title=<span class="string">&quot;&#x27;对评论点赞&#x27;&quot;</span>&gt;&lt;/van-cell&gt;</span><br><span class="line">    &lt;van-cell v-<span class="keyword">for</span>=<span class="string">&quot;(item, idx) in list&quot;</span> :key=<span class="string">&quot;idx&quot;</span>&gt;</span><br><span class="line">      &lt;span style=<span class="string">&quot;color: #466b9d;&quot;</span> slot=<span class="string">&quot;title&quot;</span>&gt;&#123;&#123; item.aut_name &#125;&#125;&lt;/span&gt;</span><br><span class="line">      &lt;div slot=<span class="string">&quot;label&quot;</span>&gt;</span><br><span class="line">        &lt;p style=<span class="string">&quot;color: #363636;&quot;</span>&gt;&#123;&#123; item.content &#125;&#125;&lt;/p&gt;</span><br><span class="line">        &lt;p&gt;</span><br><span class="line">          &lt;span style=<span class="string">&quot;margin-right: 10px;&quot;</span>&gt;&#123;&#123; item.pubdate &#125;&#125;&lt;/span&gt;</span><br><span class="line">        &lt;/p&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">      &lt;van-icon</span><br><span class="line">        slot=<span class="string">&quot;right-icon&quot;</span></span><br><span class="line">        :name=<span class="string">&quot;item.is_liking ? &#x27;like&#x27; : &#x27;like-o&#x27;&quot;</span></span><br><span class="line">        @click=<span class="string">&quot;hSwitchLike(item)&quot;</span></span><br><span class="line">      /&gt;</span><br><span class="line">    &lt;/van-cell&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  data() &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      list: [</span><br><span class="line">        &#123;</span><br><span class="line">          aut_name: <span class="string">&quot;李林森&quot;</span>,</span><br><span class="line">          content: <span class="string">&quot;言辞犀利有内涵&quot;</span>,</span><br><span class="line">          pubdate: <span class="string">&quot;2002&quot;</span>,</span><br><span class="line">          is_liking: <span class="literal">false</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          aut_name: <span class="string">&quot;李林森2&quot;</span>,</span><br><span class="line">          content: <span class="string">&quot;言辞犀利有内涵&quot;</span>,</span><br><span class="line">          pubdate: <span class="string">&quot;2002&quot;</span>,</span><br><span class="line">          is_liking: <span class="literal">false</span></span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    hSwitchLike(item) &#123;</span><br><span class="line">      item.is_liking = !item.is_liking; <span class="comment">// 注意 is_liking是数组内有的而不是后来在加的</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>在点赞中直接修改数组内对象的数据。</p>
<p>这里进一步解释：不是不能使用数组索引，而使用场景是将对象数组内部的对象属性更新，而<strong>不是直接设置修改数组</strong>，这就像使用push方法是<strong>更新数组</strong>和<strong>直接设置数组不一样</strong></p>
</li>
</ol>
<p>我们分别使用了 push、 splice 和直接修改obj内的属性。</p>
<ol start="4">
<li>原理描述：( vue 源码  node_modules\vue\dist\vue.js) 在vue的项目中才有哦~</li>
</ol>
<p>**vue源码对Array上的方法进行了监听 **（加分项）</p>
<p>在进行数据劫持之前判断数据类型。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">   * Observer class that is attached to each observed</span></span><br><span class="line"><span class="comment">   * object. Once attached, the observer converts the target</span></span><br><span class="line"><span class="comment">   * object&#x27;s property keys into getter/setters that</span></span><br><span class="line"><span class="comment">   * collect dependencies and dispatch updates.</span></span><br><span class="line"><span class="comment">   */</span> </span><br><span class="line">  <span class="keyword">var</span> Observer = <span class="function"><span class="keyword">function</span> <span class="title">Observer</span> (<span class="params">value</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.value = value;</span><br><span class="line">    <span class="built_in">this</span>.dep = <span class="keyword">new</span> Dep();</span><br><span class="line">    <span class="built_in">this</span>.vmCount = <span class="number">0</span>;</span><br><span class="line">    def(value, <span class="string">&#x27;__ob__&#x27;</span>, <span class="built_in">this</span>);</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(value)) &#123;</span><br><span class="line">      <span class="keyword">if</span> (hasProto) &#123;</span><br><span class="line">        protoAugment(value, arrayMethods);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        copyAugment(value, arrayMethods, arrayKeys);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="built_in">this</span>.observeArray(value);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="built_in">this</span>.walk(value);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure>

<p>数组处理</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">   * not type checking this file because flow doesn&#x27;t play well with</span></span><br><span class="line"><span class="comment">   * dynamically accessing methods on Array prototype</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">var</span> arrayProto = <span class="built_in">Array</span>.prototype;</span><br><span class="line">  <span class="keyword">var</span> arrayMethods = <span class="built_in">Object</span>.create(arrayProto);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">var</span> methodsToPatch = [</span><br><span class="line">    <span class="string">&#x27;push&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;pop&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;shift&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;unshift&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;splice&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;sort&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;reverse&#x27;</span></span><br><span class="line">  ];</span><br><span class="line"></span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">   * Intercept mutating methods and emit events</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">  methodsToPatch.forEach(<span class="function"><span class="keyword">function</span> (<span class="params">method</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// cache original method</span></span><br><span class="line">    <span class="keyword">var</span> original = arrayProto[method];</span><br><span class="line">    def(arrayMethods, method, <span class="function"><span class="keyword">function</span> <span class="title">mutator</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> args = [], len = <span class="built_in">arguments</span>.length;</span><br><span class="line">      <span class="keyword">while</span> ( len-- ) args[ len ] = <span class="built_in">arguments</span>[ len ];</span><br><span class="line"></span><br><span class="line">      <span class="keyword">var</span> result = original.apply(<span class="built_in">this</span>, args);</span><br><span class="line">      <span class="keyword">var</span> ob = <span class="built_in">this</span>.__ob__;</span><br><span class="line">      <span class="keyword">var</span> inserted;</span><br><span class="line">      <span class="keyword">switch</span> (method) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;push&#x27;</span>:</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;unshift&#x27;</span>:</span><br><span class="line">          inserted = args;</span><br><span class="line">          <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;splice&#x27;</span>:</span><br><span class="line">          inserted = args.slice(<span class="number">2</span>);</span><br><span class="line">          <span class="keyword">break</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (inserted) &#123; ob.observeArray(inserted); &#125;</span><br><span class="line">      <span class="comment">// notify change</span></span><br><span class="line">      ob.dep.notify();</span><br><span class="line">      <span class="keyword">return</span> result</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">/*  */</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">var</span> arrayKeys = <span class="built_in">Object</span>.getOwnPropertyNames(arrayMethods);</span><br></pre></td></tr></table></figure>

<p><strong>总结下：</strong></p>
<p>vue源码对Array上的方法进行了监听</p>
<p>数组的如下方法可以触发视图更新</p>
<p>push() // 在最后添加元素<br>pop() // 删除最后一个元素<br>shift() // 删除第一个<br>unshift() // 在开通添加<br>splice() // 曾删<br>sort() // 排序<br>reverse() // 反转</p>
<p>$set的原理(加分项)</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Set a property on an object. Adds the new property and</span></span><br><span class="line"><span class="comment"> * triggers change notification if the property doesn&#x27;t</span></span><br><span class="line"><span class="comment"> * already exist.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">set</span> (<span class="params">target, key, val</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 先判断target是不是undefined、null、string、number、symbol、boolean</span></span><br><span class="line">  <span class="keyword">if</span> (isUndef(target) || isPrimitive(target)</span><br><span class="line">  ) &#123;</span><br><span class="line">    warn((<span class="string">&quot;Cannot set reactive property on undefined, null, or primitive value: &quot;</span> + ((target))));</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 如果target是一个数组，那么根据key值及数组长度更改数组的长度(取其中较大者)，然后直接使用splice函数修改数组</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(target) &amp;&amp; isValidArrayIndex(key)) &#123;</span><br><span class="line">    target.length = <span class="built_in">Math</span>.max(target.length, key);</span><br><span class="line">    target.splice(key, <span class="number">1</span>, val);</span><br><span class="line">    <span class="keyword">return</span> val</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 属性key存在于target对象中且key不是Object.prototype上的属性时</span></span><br><span class="line">  <span class="keyword">if</span> (key <span class="keyword">in</span> target &amp;&amp; !(key <span class="keyword">in</span> <span class="built_in">Object</span>.prototype)) &#123;</span><br><span class="line">    target[key] = val;</span><br><span class="line">    <span class="keyword">return</span> val</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// target 是一个对象 ，key不存在于target </span></span><br><span class="line">  <span class="keyword">var</span> ob = (target).__ob__;</span><br><span class="line">    <span class="comment">//当target为vue实例或根数据data对象时</span></span><br><span class="line">  <span class="keyword">if</span> (target._isVue || (ob &amp;&amp; ob.vmCount)) &#123;</span><br><span class="line">    warn(</span><br><span class="line">      <span class="string">&#x27;Avoid adding reactive properties to a Vue instance or its root $data &#x27;</span> +</span><br><span class="line">      <span class="string">&#x27;at runtime - declare it upfront in the data option.&#x27;</span></span><br><span class="line">    );</span><br><span class="line">    <span class="keyword">return</span> val</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (!ob) &#123;</span><br><span class="line">    target[key] = val;</span><br><span class="line">    <span class="keyword">return</span> val</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//新加的属性添加依赖</span></span><br><span class="line">  defineReactive$$<span class="number">1</span>(ob.value, key, val);</span><br><span class="line">  <span class="comment">// 触发当前的依赖 </span></span><br><span class="line">  ob.dep.notify();</span><br><span class="line">  <span class="keyword">return</span> val</span><br><span class="line">&#125;</span><br><span class="line">....</span><br><span class="line">Vue.prototype.$set = set;</span><br></pre></td></tr></table></figure>

<p>我们只要清楚作者设计 set的 <strong>思路</strong> 就行啦</p>
<ol>
<li><p><strong>先判断target类型</strong>。是不是undefined、null、string、number、symbol、boolean</p>
</li>
<li><p><strong>如果target是一个数组</strong>，那么根据key值及数组长度更改数组的长度(取其中较大者)，然后直接<strong>使用splice函数修改数组</strong>，虽然vue没有监听数组变化，但是监听了数组的<code>push,pop,shift,unshift,splice,sort,reverse</code>函数，所以使用splice也可以达到更新dom的目的</p>
</li>
<li><p><strong>如果属性key存在于target对象中且key不是Object.prototype上的属性时</strong>，表明这是在修改target对象属性key的值（不管target对象是否是响应式的，只要key存在于target对象中，就执行这一步逻辑），此时就直接将value直接赋值给target[key]；</p>
</li>
<li><p><strong>判断target，当target为vue实例或根数据data对象</strong>时，在开发环境下抛错；</p>
</li>
<li><p><code>defineReactive(ob.value, key, val)</code>的意思是给新加的属性添加依赖，以后再直接修改这个新的属性的时候就会触发页面渲染。</p>
<p><code>ob.dep.notify()</code>这句代码的意思是触发当前的依赖（这里的依赖依然可以理解成渲染函数），所以页面就会进行重新渲染。</p>
</li>
</ol>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ol>
<li>回答问题的产生原因。（证明自己基础很好）</li>
<li>举例子对这个问题进一步解释。</li>
<li>结合项目中我们是如何使用避免这个问题。（体现项目经验）</li>
<li>原理分析。（+鸡腿）</li>
</ol>
<p>完整案例下载：<a target="_blank" rel="noopener" href="https://gitee.com/linrufeng/interview.git">https://gitee.com/linrufeng/interview.git</a></p>

        <!-- 分类文章 -->
        
      </div>
      <div class="post-content-inner-space">
        
          <div class="space-toc-main animate__animated  animate__fadeInUp">
            <ol class="space-toc"><li class="space-toc-item space-toc-level-3"><a class="space-toc-link" href="#%E7%9B%AE%E7%9A%84"><span class="space-toc-text">目的</span></a></li><li class="space-toc-item space-toc-level-3"><a class="space-toc-link" href="#%E9%97%AE%E9%A2%98"><span class="space-toc-text">问题</span></a></li><li class="space-toc-item space-toc-level-3"><a class="space-toc-link" href="#%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B%EF%BC%88%E9%81%87%E5%88%B0%E8%BF%99%E7%B1%BB%E9%97%AE%E9%A2%98%E7%9A%84%E6%80%9D%E8%B7%AF%EF%BC%89"><span class="space-toc-text">解析过程（遇到这类问题的思路）</span></a></li><li class="space-toc-item space-toc-level-3"><a class="space-toc-link" href="#%E6%80%BB%E7%BB%93"><span class="space-toc-text">总结</span></a></li></ol>
           </div>
        
      </div>
   </div>
    <!-- 评论 -->
    
    <div class="bottom-comments-outer">
      <div class="bottom-comments-inner">
        <!-- valine -->
        
        <!-- Gitalk -->
        
        <!-- livere -->
        
        </div>
      </div>
    
  </div>
</article>
  </div>
</div>



<!-- 如果是home模式的话，不在首页就显示footer，如果不是home模式的话 所有都显示footer -->

  <div class="footer-outer animate__animated  animate__fadeInUp">
    <div class="footer-inner">
    <div class="footer-text">
    <p>黑马培训前端</p>

    </div>
    <div class="footer-contact">
    <ul class="footer-ul">
        
        <li class="footer-li">
            <a href="https://github.com/FuShaoLei/hexo-theme-white" target="_blank">
                <i class="ri-github-line"></i>
            </a>
        </li>
        
        <li class="footer-li">
            <a href="mailto:1563250958@qq.com" target="_blank">
                <i class="ri-mail-line"></i>
            </a>
        </li>
        
    </ul>
    </div>
    </div>
</div>






<script src="/blog/js/white.js"></script>


<script src="/blog/js/highlight.js"></script>

<script>hljs.initHighlightingOnLoad();</script>

</body>
</html>
